package NG::Chat::Chanel;
use strict;
use warnings;
use utf8;

#use NG::Chat::Util;
#use NG::Sys::Text;

sub Create {
	my $app = shift;
	my %obj = (app => $app);
	# список клиентов по логинам
	$obj{chanels} = {};
	my $self = bless \%obj,__PACKAGE__;
	my $cl = $app->reference("chanel_list");
	for my $desc(@{$cl->get_list}){
		unless($desc->{template}){
			$self->create_chanel($desc->{name},$desc->{title},$desc->{param});
		}
	}
	$self->create_chanel("default","default",{nolist=>1,close=>1});
	return $self;
}
sub cleanup {
	my $self = shift;
	delete $self->{app};
	delete $self->{chanels};
}

sub get_chanel {
	my ($self,$id) = @_;
	return $self->{chanels}{$id};
}

sub list_logins {
	my ($self,$login,$id) = @_;
	unless(my $c = $self->{chanels}{$id}){
		return "";
	}elsif($c->{list}{$login} or $login =~/^admin/){
		if($c->{nolist}){
			return [];
		}else{
			return [ sort keys %{$c->{list_title}} ];
		}
	}else{
		return "";
	}
}
sub create_chanel {
	my ($self,$id,$title,$param) = @_;
	if($self->{chanels}{$id}){
		return {error=>409,text=>"chanel [$id] exists"};
	}else{
		$self->{chanels}{$id} = {
			close => $param->{close},
			nolist => $param->{nolist},
			owner => $param->{owner} || "admin",
			messages => [],
			shift => 0,
			list => {},
			list_title => {},
			create => time(),
			last => time(),
			access => $param->{access} || 0760,
			perm => $param->{perm},
			title => $title || $id,
		};
		return 0;
	}
}
sub remove_chanel {
	my ($self,$id) = @_;
	unless(my $c = $self->{chanels}{$id}){
		return {error=>404,text=>"chanel [$id] not found"};
	}else{
		my $ch = delete $self->{chanels}{$id};
		$ch->{lister}->stop if $ch->{lister};
		for my $u(@{$ch->{list}}){
			delete $self->{app}{'chat-login'}{logins}{$u}{chanels}{$id};
		}
		$ch->{messages} = undef;
		$ch->{list} = undef;
		return 0;
	}
}
sub join_login{
	my($self,$login,$id) = @_;
	if(my $c = $self->{chanels}{$id}){
		$c->{list}{$login} = 1;
		(my $lgn = $self->{app}{'chat-login'}{logins}{$login})->{chanels}{$id} = $c->{shift} + @{$c->{messages}};
		unless($c->{nolist} or $lgn->{nolist}){
			$c->{list_title}{$lgn->{title}} = 1;
			#$c->{list_str} = join(", ", sort keys %{$c->{list_title}});
			$self->{app}{'chat-command'}->put_message({type=>"notice", param1 => "join", param2 => $lgn->{title},
								chanel => $id ,chaneltitle => $c->{title}});
		}
		return $c->{title};
	}else{
		return 0;
	}
}
#sub rejoin_login{
#	my($self,$login,$newlogin,$id) = @_;
#	if(my $c = $self->{chanels}{$id}){
#		delete $c->{list}{$login};
#		$c->{list}{$newlogin} = 1;
#		unless($c->{nolist}){
##			$c->{list_str} = join(", ", keys %{$c->{list}});
#			$self->{app}{'chat-command'}->put_message({type=>"notice", param1 => "rejoin", param2 => $login, param3 => $newlogin, chanel => $id});
#		}
#		return $c->{title};
#	}else{
#		return 0;
#	}
#}
sub split_login {
	my($self,$login,$id,$new_sid) = @_;
	if(my $c = $self->{chanels}{$id}){
		delete $c->{list}{$login};
		delete((my $lgn = $self->{app}{'chat-login'}{logins}{$login})->{chanels}{$id});
		unless($c->{nolist} or $lgn->{nolist}){
			delete $c->{list_title}{$lgn->{title}};
			#$c->{list_str} = join(", ", sort keys %{$c->{list_title}});
			unless(scalar %{$c->{list_title}} or $c->{perm}){
				$c->{messages} = undef;
				$c->{list} = undef;
				delete $self->{chanels}{$id};
			}elsif(!$new_sid){
				$self->{app}{'chat-command'}->put_message({type=>"notice",param1 => "leave", param2 => $lgn->{title},
												chanel => $id});
			}
		}
		return 1;
	}else{
		return 0;
	}
}
sub can_join {
	my ($self,$chanel,$login) = @_;
	unless($chanel){
		return {error=>400,text=>"no chanel"};
	}elsif(!$login){
		return {error=>400,text=>"no login"};
	}elsif(my $c = $self->{chanels}{$chanel}){
		if($c->{list}{$login}){
			return {error=>409,text=>"[$login] already joined to chanel [$chanel]"};
		}else{
			return 0;
		}
	}else{
		return {error=>404,text=>"chanel [$chanel} not found"};
	}
}
sub can_split {
	my ($self,$chanel,$login) = @_;
	unless($chanel){
		return {error=>400,text=>"no chanel"};
	}elsif(!$login){
		return {error=>400,text=>"no login"};
	}elsif(my $c = $self->{chanels}{$chanel}){
		if($c->{list}{$login}){
			return 0;
		}else{
			return {error=>404,text=>"not joined"};
		}
	}else{
		return {error=>404,text=>"chanel [$chanel} not found"};
	}
}
sub can_create {
	my ($self,$chanel,$login) = @_;
	unless($chanel){
		return {error=>400,text=>"no chanel"};
	}elsif(!$login){
		return {error=>400,text=>"no login"};
	}elsif(my $c = $self->{chanels}{$chanel}){
		return {error=>409,text=>"chanel [$chanel} exists"};
	}elsif($login =~/^admin/){
		return 0;
	}else{
		return {error=>403,text=>"not permitted"};
	}
}
sub can_remove {
	my ($self,$chanel,$login) = @_;
	unless($chanel){
		return {error=>400,text=>"no chanel"};
	}elsif(!$login){
		return {error=>400,text=>"no login"};
	}elsif(my $c = $self->{chanels}{$chanel}){
		if($login =~ /^admin/){
			return 0;
		}else{
			return {error=>403,text=>"not permitted"};
		}
	}else{
		return {error=>404,text=>"chanel [$chanel} not found"};
	}
}
sub can_message {
	my ($self,$chanel,$login) = @_;
	unless($chanel){
		return {error=>400,text=>"no chanel"};
	}elsif(!$login){
		return {error=>400,text=>"no login"};
	}elsif(my $c = $self->{chanels}{$chanel}){
		my $is_admin = $login =~ /^admin/;
		unless($c->{list}{$login} || $is_admin){
			return {error=>403,text=>"not in list"};
		}elsif($c->{readonly} && !$is_admin){
			return {error=>403,text=>"read only"};
		}else{
			return 0;
		}
	}else{
		return {error=>404,text=>"chanel [$chanel} not found"};
	}
}
sub can_list {
	my ($self,$chanel,$login) = @_;
	unless($chanel){
		return {error=>400,text=>"no chanel"};
	}elsif(!$login){
		return {error=>400,text=>"no login"};
	}elsif(my $c = $self->{chanels}{$chanel}){
		if($c->{list}{$login}){
			return 0;
		}elsif($login =~ /^admin/){
			return 0;
		}else{
			return {error=>403,text=>"not permitted"};
		}
	}else{
		return {error=>404,text=>"chanel [$chanel} not found"};
	}
}

1;
